
// 触摸组件
export namespace lib {
    const {ccclass} = cc._decorator;

    @ccclass
    export class TouchCpt extends cc.Component { 
        // 是否可触摸
        isTouches: boolean = true;
        // 是否停止向上传递
        isStopPropagation:boolean = true;
        // 是否单点触摸
        isTouchOneByOne: boolean = true;
        // 是否执行缩小放大
        isScaleEffect: boolean = true;
        scaleValue: number = 0.95;
        // 回调函数目标
        target: object = null;

        private _eventId:number = -1;
        private _originalScaleX: number = 0;
        private _originalScaleY: number = 0;

        // 是否添加过事件
        private _isAddTouches: boolean = false;

        private _beginFunc:Function = null;
        private _moveFunc:Function = null;
        private _cancelFunc:Function = null;
        private _endFunc:Function = null;

        // 持续点击时间间隔
        lastDuration:number = 0;
        private _lastFunc:Function = null;

        // 添加额外点击
        private _extraOnce:boolean = true;
        private _extraFunc:Function = null;
        private _extraTarget:object = null;

        // 双击
        private _doubleTime:number = 0.3;
        private _doubleFunc:Function = null;
        private _scheduDouble:Function = null;
        private _clickNum:number = 0;

        // 声音
        soundName:string = '';

        onLoad() {
            // 默认加载事件
            this.addTouchEvents();
        }

        // 隐藏回调
        onDisable() {
            this._restore();
        }

        private doCallback (func?:Function, event?:cc.Event.EventTouch, target?:object) {
            if(func) {
                return func.call(target || this.target, event);
            }
            return null;
        }

        private onTouchBegin(event:cc.Event.EventTouch) {
            if(!this.isTouches) {
                return ;
            }

            if(this.isTouchOneByOne && this._eventId >= 0) {
                return ;
            }

            if(this.isStopPropagation) {
                event.stopPropagation();
            }

            this._eventId = event.getID();
            if(this.isScaleEffect && this._originalScaleX == 0) {
                this._originalScaleX = this.node.scaleX;
                this._originalScaleY = this.node.scaleY;
                this.node.setScale(this._originalScaleX * this.scaleValue, this._originalScaleY * this.scaleValue);
            }

            if(this._doubleFunc) {
                
            } else if(this.lastDuration > 0) {
                if(this._lastFunc) {
                    this.unschedule(this._lastFunc);
                }
                this._lastFunc = ()=>{
                    this.doCallback(this._beginFunc, event);
                }
                this.schedule(this._lastFunc, this.lastDuration);
            } else {
                this.doCallback(this._beginFunc, event);
            }
        }

        private onTouchMove(event:cc.Event.EventTouch) {
            if(!this._isCheck(event)) {
                return ;
            }

            this.doCallback(this._moveFunc, event);
        }

        private onTouchCancel(event:cc.Event.EventTouch) {
            if(!this._isCheck(event)) {
                return ;
            }

            this._restore();
            this.doCallback(this._cancelFunc, event);
            // if(this._doubleFunc) {
            //     this._cancelDoubleClick();
            // }
        }

        private onTouchEnd(event:cc.Event.EventTouch) {
            if(!this._isCheck(event)) {
                return ;
            }

            this._restore();
            this.doCallback(this._extraFunc, event, this._extraTarget);
            if(this._extraOnce) {
                this._extraFunc = null;
                this._extraTarget = null;
            }

            // 双击处理
            if(this._doubleFunc) {
                this._clickNum ++;
                if(this._clickNum == 1) {
                    this._scheduDouble = ()=>{
                        if(this._clickNum > 1) {
                            this.doCallback(this._doubleFunc, event);
                        } else {
                            this.doCallback(this._endFunc, event);
                        }
                        this._clickNum = 0;
                        this._scheduDouble = null;
                    }
                    this.scheduleOnce(this._scheduDouble, this._doubleTime);
                } else if(this._clickNum > 1) {
                    this.doCallback(this._doubleFunc, event);
                    this._cancelDoubleClick();
                }
            } else {
                this.doCallback(this._endFunc, event);
            }
            
            // JsBridge.playSound(this.soundName);
        }

        // 取消双击
        private _cancelDoubleClick() {
            this._clickNum = 0;
            if(this._scheduDouble) {
                this.unschedule(this._scheduDouble);
                this._scheduDouble = null;
            }
        }

        // 判断是否合法
        private _isCheck(event:cc.Event.EventTouch) {
            if(!this.isTouches) {
                return false;
            }

            if(this.isTouchOneByOne && this._eventId != event.getID()) {  // 不是之前的点击事件
                return false;
            }

            if(this.isStopPropagation) {
                event.stopPropagation();
            }
            return true;
        }

        // 还原
        private _restore() {
            this._eventId = -1;
            if(this._originalScaleX != 0) {
                this.node.setScale(this._originalScaleX, this._originalScaleY);
                this._originalScaleX = 0;
                //console.log('TouchCpt', '_restore', this.node.name);
            }
            if(this._lastFunc) {
                this.unschedule(this._lastFunc);
                this._lastFunc = null;
            }
        }

        // 添加触摸事件
        addTouchEvents() {
            if(!this._isAddTouches) {
                this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchBegin, this);
                this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
                this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
                this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this); 
                this._isAddTouches = true;
            }
        }

        // 清除触摸事件
        clearTouchEvents() {
            if(this._isAddTouches) {
                this._isAddTouches = false;
                this.node.off(cc.Node.EventType.TOUCH_START, this.onTouchBegin, this);
                this.node.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
                this.node.off(cc.Node.EventType.TOUCH_CANCEL, this.onTouchCancel, this);
                this.node.off(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this); 

                this._cancelDoubleClick();
            }
        }

        // 设置穿透 false
        setSwallowTouches(isSwallow:boolean) {
            this.addTouchEvents();

            this.isStopPropagation = isSwallow;

            let _touchListener = this.node['_touchListener'];
            if(_touchListener && _touchListener.setSwallowTouches) {
                _touchListener.setSwallowTouches(isSwallow);
            }
        }

        // 设置触摸事件
        setTouchEvents(endFunc?: Function, beginFunc?: Function, moveFunc?: Function, cancelFunc?: Function, target?:object) {
            this._endFunc = endFunc;
            this._beginFunc = beginFunc;
            this._moveFunc = moveFunc;
            this._cancelFunc = cancelFunc;
            this.target = target;

            this.addTouchEvents();
        }

        setTouchEvent(eventType = cc.Node.EventType.TOUCH_END, func?:Function, target?:object) {
            switch(eventType) {
                case cc.Node.EventType.TOUCH_END:
                    this._endFunc = func;
                    break;
                case cc.Node.EventType.TOUCH_START:
                    this._beginFunc = func;
                    break;
                case cc.Node.EventType.TOUCH_MOVE:
                    this._moveFunc = func;
                    break;
                case cc.Node.EventType.TOUCH_CANCEL:
                    this._cancelFunc = func;
                    break;
            }
            this.target = target;
            this.addTouchEvents();
        }

        // 设置持续点击
        setLastTouchEvent(func:Function, duration:number = 0.3, target?:object, endFunc?:Function) {
            this.lastDuration = duration;
            this.target = target; 
            this._beginFunc = func;
            this._cancelFunc = endFunc;
            this._endFunc = endFunc;
            this.addTouchEvents();
        }

        addExtraTouchEvent(func:Function, once:boolean = true, target?:object) {
            this._extraFunc = func;
            this._extraTarget = target;
            this._extraOnce = once;
        }

        // 设置双击
        setDoubleClickEvent(doubleClick:Function, func:Function, target?:object, time:number = 0.3) {
            this._doubleFunc = doubleClick;
            this._endFunc = func;
            this.target = target;
            this._doubleTime = time;
            this.addTouchEvents();
        }
    }
}